package main

import (
	"fmt"
	"time"
)

func main() {
	//map和切片都是引用类型, 因此当 map 类型变量作为参数被传递给函数或方法的时候，在函数内部对 map 的修改会影响函数外部的值
	m := make(map[int]string)
	m[1] = "value1"
	m[3] = "value2"
	foo(m)
	fmt.Println(m) //map[1:changed 3:value2]

	//因为 map 可以自动扩容，map 中数据元素的 value 位置可能在这一过程中发生变化，所以 Go 不允许获取 map 中 value 的地址
	//p := &m[1] //invalid operation: cannot take address of m[1] (map index expression of type string)

	//map的并发问题,不支持同时并发读写
	mx := map[int]int{
		1: 11,
		2: 12,
		3: 13,
	}

	go func() {
		for i := 0; i < 1000; i++ {
			doIteration(mx)
		}
	}()

	go func() {
		for i := 0; i < 1000; i++ {
			doWrite(mx)
		}
	}()
	time.Sleep(5 * time.Second)
	//执行后报错:fatal error: concurrent map iteration and map write
	//把上面的 doIteration() 和 doWrite() 任意一个注释掉就OK了
}

func foo(data map[int]string) {
	data[1] = "changed"
}

func doIteration(m map[int]int) {
	for k, v := range m {
		_ = fmt.Sprintf("[%d, %d] ", k, v)
	}
}
func doWrite(m map[int]int) {
	for k, v := range m {
		m[k] = v + 1
	}
}
